home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / misc / CapiRexxVoiceM.lha / MyCAPI.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-19  |  15.5 KB  |  638 lines

  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. #include <proto/dos.h>
  5. #include <libraries/dos.h>
  6.  
  7. #include "os.h"
  8. #include "capi-usr.h"
  9.  
  10. #include "MyCAPI.h"
  11.  
  12.  
  13. /*
  14. ** einige in ETSI definierte Konstanten
  15. */
  16. #define D_ALERTING                    0x01
  17. #define D_CALL_PROCEEDING            0x02
  18. #define D_SETUP_ACKNOWLEDGE        0x0D
  19. #define I_Cause                        0x08
  20. #define I_ChannelIdentification    0x18
  21. #define I_Facility                    0x1C
  22. #define I_DateTime                    0x29
  23.  
  24.  
  25. /*
  26. ** ist das richtig ???
  27. */
  28. #define I_Charging                    0x4001
  29.  
  30.  
  31. /*
  32. ** Text-Highlighting
  33. */
  34. #define HI_ON    "\x1b[32m"
  35. #define HI_OFF    "\x1b[31m"
  36. #define NAMELEN 50
  37. #define MAXLINELEN 512
  38.  
  39. /*
  40. ** Externals
  41. */
  42. extern BOOL debugcapi;
  43. extern U8 *actioncmd;
  44. extern U8 *phonebook;
  45. extern U8   outputbuff[];
  46. extern struct Task *maintask;
  47. extern VOID myoutput(U8 *, ...);
  48. extern FILE *phonebookfile;
  49.  
  50.  
  51. /*
  52. ** Locals
  53. */
  54. static U16 ApplID;
  55. static U8  manufacturer[64];
  56. static U32 version[4];
  57. static U8  serialnumber[8];
  58.  
  59.  
  60. /*
  61. ** Code
  62. */
  63.  
  64. /****************************************************************************
  65. **    Ausgaben aus dem CAPI-Callback heraus sollten wir tunlichst
  66. ** vermeiden (Device-Context !). Daher der Weg ueber eine globale
  67. ** Variable und ein Signal.
  68. */
  69. static VOID out(BOOL flag, U8 *fmt, ...)
  70. {
  71.     va_list arg;
  72.  
  73.     if (flag) {
  74.         va_start(arg, fmt);
  75.         vsprintf(outputbuff, fmt, arg);
  76.         va_end(arg);
  77.         Signal( maintask, SIGF_SINGLE );
  78.     }
  79. }
  80.  
  81.  
  82. /****************************************************************************
  83. **    Aus einem Array von CAPI-`struct's einen Zeiger auf die <num>te
  84. ** struct (d.h. auf das Laengenbyte) zurueckgeben
  85. */
  86.  
  87. static U8 *GetStruct( U8 *ptr, int num )
  88. {
  89.     while (num > 0) {
  90.         if (*ptr == 0xFF)
  91.             ptr += (GET_U16(ptr+1) + 3);
  92.         else
  93.             ptr += *ptr + 1;
  94.         num--;
  95.     }
  96.     return ptr;
  97. }
  98.  
  99.  
  100. /****************************************************************************
  101. **    Eine CAPI-Message an den CAPI Treiber schicken
  102. */
  103. static U32 SendCAPIMessage( U16 applID, CAPI_MESSAGE *msg, U8 *end )
  104. {
  105.     msg->TotalLength = end - (U8 *)msg;
  106.     return (U32)U_CAPI_PUT_MESSAGE( applID, msg );
  107. }
  108.  
  109.  
  110. /*****************************************************************************
  111. ** Ermittelt eine evtl. uebertragene CallingNumber
  112. */
  113. static VOID GetCallingPartyName(U8 *name, U8 *number)
  114. {
  115.     U8 rline[MAXLINELEN];
  116.     U8 number1[NAMELEN+2];
  117.     U8 number2[NAMELEN+4];
  118.     U8 index;
  119.     U8 index2;
  120.     U8 anfang;
  121.     U8 ende;
  122.     
  123.     BOOL status;
  124.     
  125.     if(number[0]=='\0')
  126.     {
  127.         name[0]='\0';
  128.         return;
  129.     }
  130.     
  131.     number1[0]='P';
  132.     number1[1]='=';
  133.     number1[2]='\0';
  134.     
  135.     number2[0]='P';
  136.     number2[1]='=';
  137.     number2[2]='"';
  138.     number2[3]='\0';
  139.     
  140.     strcat(number1,number);
  141.     strcat(number2,number);
  142.     
  143.     strcat(number2,"\"");
  144.  
  145.     name[0]='\0';
  146.     
  147.     if (phonebook != NULL)
  148.     {
  149.         if (phonebookfile = fopen(phonebook,"r"))
  150.         {
  151.             while ((fgets(rline, MAXLINELEN, phonebookfile) != NULL) && (name[0] == '\0'))
  152.             {
  153.                 if ((strstr(rline,number1) != NULL) || (strstr(rline,number2) != NULL))
  154.                 {
  155.                     status=FALSE;
  156.                     anfang=0;
  157.                     ende=0;
  158.                     for(index=0;index<=strlen(rline);index++)
  159.                     {
  160.                         switch(rline[index])
  161.                         {
  162.                         case '"' :
  163.                             status = (status==TRUE) ? FALSE : TRUE;
  164.                             break;
  165.                         case '=' :
  166.                             if ((rline[index-1] == 'N') && (status==FALSE))
  167.                             {
  168.                                 index++;
  169.                                 anfang = (rline[index] == '"') ? index+1 : index;
  170.                                 while(!((rline[index] == ' ') && (status == FALSE)) && !((rline[index] == '"') && (status == TRUE)) && !(rline[index] == '\0'))
  171.                                 {
  172.                                     if(rline[index]=='"')
  173.                                     {
  174.                                         status = (status==TRUE) ? FALSE : TRUE;
  175.                                     }
  176.                                     index++;
  177.                                 }
  178.                                 ende = (rline[index-1]=='"') ? index-1 : index;
  179.                                 ende = ((ende-anfang)>=(NAMELEN-1)) ? (anfang+NAMELEN-1) : ende;
  180.                                 for(index2=anfang;index2<ende;index2++)
  181.                                 {
  182.                                     name[index2-anfang]=rline[index2];
  183.                                 }
  184.                                 name[index2-anfang]='\0';
  185.                             }
  186.                             break;
  187.                         }
  188.                     }
  189.                 }
  190.             }
  191.             fclose(phonebookfile);
  192.         }
  193.     }
  194.     return;
  195. }
  196.  
  197.  
  198. /*****************************************************************************
  199. ** Ermittelt eine evtl. uebertragene CallingNumber
  200. */
  201. static VOID GetCallingPartyNumber(U8 *p, U8 *callingparty)
  202. {
  203.     U8 len, type, plan, presentation;
  204.  
  205.     if ((len = callingparty[0]) > 1) {
  206.  
  207.         /*
  208.         ** Number Type ermitteln
  209.         */
  210.         type = (callingparty[1] & 0x70) >> 4;
  211.  
  212.         /*
  213.         ** Numbering plan ermitteln
  214.         */
  215.         plan = (callingparty[1] & 0x0F);
  216.  
  217.         /*
  218.         ** Presentation and Screening Indicator ermitteln
  219.         */
  220.         presentation = callingparty[2] & 0x7F;
  221.  
  222.         switch (type) {
  223.             case 0x00:             /* unknown type */
  224.                 break;
  225.             case 0x01:             /* international number */
  226.                 break;
  227.             case 0x02:             /* national number */
  228.                 *p++ = '0';
  229.                 break;
  230.             case 0x03:             /* network specific number */
  231.                 break;
  232.             case 0x04:             /* subsciber number */
  233.                 break;
  234.             case 0x06:             /* abbreviated number */
  235.                 break;
  236.             default:             /* reserved */
  237.                 break;
  238.         }
  239.         strncpy(p, &callingparty[3], len-2);
  240.         *(p + len - 2) = '\0';
  241.     } else
  242.         strcpy(p, "<Analog>");
  243. }
  244.  
  245.  
  246. /*****************************************************************************
  247. ** Ermittelt eine evtl. uebertragene CalledNumber
  248. */
  249. static VOID GetCalledPartyNumber(U8 *p, U8 *calledparty)
  250. {
  251.     strncpy(p, &calledparty[2], calledparty[0]-1);
  252.     p[calledparty[0]-1] = '\0';
  253. }
  254.  
  255.  
  256. /*****************************************************************************
  257. ** Unser (zugegeben einfacher) CAPI-Signalhandler
  258. ** (komplexere Applikationen muessen natuerlich auch andere Messages
  259. ** auswerten und darauf antworten; wir haben es hier einfacher, da
  260. ** nur LISTEN_CONF, CONNECT_IND, DISCONNECT_IND und INFO_IND kommen
  261. ** koennen)
  262. ** data ist der bei U_CAPI_SET_SIGNAL uebergebene Parameter (bei
  263. ** uns hier NULL)
  264. */
  265. static VOID __saveds SignalHandler( U16 applIDdummy, U32 data )
  266. {
  267.  
  268.     CAPI_MESSAGE *rmsg;
  269.     U32 error;
  270.     BPTR nullfh1, nullfh2;
  271.     nullfh1 = nullfh2 = NULL;
  272.  
  273.     for (;;) {
  274.         U8 *para;
  275.  
  276.         /*
  277.         ** CAPI-Messages vom Treiber abholen und bearbeiten
  278.         */
  279.         error = U_CAPI_GET_MESSAGE( ApplID, &rmsg );
  280.         if (error == 0) {
  281.             if (rmsg) {
  282.  
  283.                 /*
  284.                 ** Auf Parameterblock setzen
  285.                 */
  286.                 para = INIT_PARA( rmsg );
  287.                 switch (rmsg->Subcommand) {
  288.  
  289.                     case CAPISUBCMD_CONF:
  290.                         switch (rmsg->Command) {
  291.  
  292.                             case CAPICMD_LISTEN:
  293.                                 out(debugcapi, "LISTEN_CONF");
  294.                                 break;
  295.  
  296.                             default:
  297.                                 out(debugcapi, "Unknown CONF <0x%04x>", rmsg->Command);
  298.                                 break;
  299.                         }
  300.                         break;
  301.  
  302.                     case CAPISUBCMD_IND:
  303.                         switch (rmsg->Command) {
  304.  
  305.                             case CAPICMD_CONNECT:
  306.                                 {
  307.                                     U32 plci;
  308.                                     U16 cip;
  309.                                     U16 resp = CAPI_REJECT_IGNORE;
  310.                                     U8  *calledparty;
  311.                                     U8  *callingparty;
  312.                                     U8  number[CAPI_MAX_NUMBER_SIZE];
  313.                                     U8  cnumber[CAPI_MAX_NUMBER_SIZE];
  314.                                     U8    name[NAMELEN];
  315.  
  316.                                     GET_PARA( para, U32, plci );
  317.                                     GET_PARA( para, U16, cip );
  318.                                     out(debugcapi, "CONNECT_IND 0x%08lx 0x%04x", plci, cip);
  319.                                     calledparty = GetStruct( para, 0 );
  320.                                     callingparty = GetStruct( para, 1 );
  321.                                     GetCallingPartyNumber(number, callingparty);
  322.                                     GetCalledPartyNumber(cnumber, calledparty);
  323.                                     GetCallingPartyName(name, number);
  324.                                     
  325.                                     out(TRUE, "%s %s %s", cnumber, number, name);
  326.                                     if (actioncmd != NULL)
  327.                                     {
  328.                                         U8 cnta;
  329.                                         U8 tmp;
  330.                                         U8 cntc=0;
  331.                                         U8 cmd[MAXLINELEN];
  332.                                         
  333.                                         for(cnta=0;cnta<strlen(actioncmd);cnta++)
  334.                                         {
  335.                                             if((actioncmd[cnta]=='%') && (cnta<(strlen(actioncmd)-1)))
  336.                                             {
  337.                                                 switch(actioncmd[cnta+1])
  338.                                                 {
  339.                                                 case 's':
  340.                                                     cmd[cntc]='\0';
  341.                                                     tmp=48+(cip/10000)%10;
  342.                                                     strcat(cmd,&tmp);
  343.                                                     tmp=48+(cip/ 1000)%10;
  344.                                                     strcat(cmd,&tmp);
  345.                                                     tmp=48+(cip/  100)%10;
  346.                                                     strcat(cmd,&tmp);
  347.                                                     tmp=48+(cip/   10)%10;
  348.                                                     strcat(cmd,&tmp);
  349.                                                     tmp=48+(cip/    1)%10;
  350.                                                     strcat(cmd,&tmp);
  351.                                                     cntc=cntc+5;
  352.                                                     break;
  353.                                                 case 'c':
  354.                                                     cmd[cntc]='\0';
  355.                                                     strcat(cmd,number);
  356.                                                     cntc=cntc+strlen(number);
  357.                                                     break;
  358.                                                 case 'm':
  359.                                                     cmd[cntc]='\0';
  360.                                                     strcat(cmd,cnumber);
  361.                                                     cntc=cntc+strlen(cnumber);
  362.                                                     break;
  363.                                                 case 'n':
  364.                                                     cmd[cntc]='\0';
  365.                                                     strcat(cmd,name);
  366.                                                     cntc=cntc+strlen(name);
  367.                                                     break;
  368.                                                 default:
  369.                                                     cmd[cntc]='%';
  370.                                                     cntc++;
  371.                                                     cmd[cntc]=actioncmd[cnta+1];
  372.                                                     cntc++;
  373.                                                     break;
  374.                                                 }
  375.                                                 cnta++;
  376.                                             }
  377.                                             else
  378.                                             {
  379.                                                 cmd[cntc]=actioncmd[cnta];
  380.                                                 cntc++;
  381.                                             }
  382.                                         }
  383.                                         cmd[cntc]='\0';
  384.                                         (void)Execute(cmd,nullfh1,nullfh2);
  385.                                     } 
  386.  
  387.                                     /*
  388.                                     ** Antwort-Message zusammenfuegen
  389.                                     */
  390.                                     para = INIT_PARA( rmsg ) + 4;    /* PLCI uebernehmen */
  391.                                     ADD_PARA( para, U16, resp );
  392.                                     ADD_PARA( para, U8, 0 );        /* Struct BProtocol */
  393.                                     ADD_PARA( para, U8, 0 );        /* Struct ConnectedNumber */
  394.                                     ADD_PARA( para, U8, 0 );        /* Struct ConnectedSubaddress */
  395.                                     ADD_PARA( para, U8, 0 );        /* Struct LLC */
  396.                                     ADD_PARA( para, U8, 0 );        /* Struct AdditionalInfo */
  397.                                     rmsg->Subcommand = CAPISUBCMD_RESP;
  398.                                     out(debugcapi, "CONNECT_RESP(0x%04x) --> 0x%04lx", resp, error);
  399.                                     error = SendCAPIMessage( ApplID, rmsg, para );
  400.                                 }
  401.                                 break;
  402.  
  403.                             case CAPICMD_DISCONNECT:
  404.                                 {
  405.                                     U32 plci;
  406.                                     U16 reason;
  407.  
  408.                                     GET_PARA( para, U32, plci );
  409.                                     GET_PARA( para, U16, reason );
  410.                                     out(debugcapi, "DISCONNECT_IND");
  411.  
  412.                                     /*
  413.                                     ** Antwort-Message zusammenfuegen
  414.                                     */
  415.                                     para = INIT_PARA( rmsg ) + 4;                /* PLCI uebernehmen */
  416.                                     rmsg->Subcommand = CAPISUBCMD_RESP;
  417.                                     out(debugcapi, "DISCONNECT_RESP --> 0x%04lx", error);
  418.                                     error = SendCAPIMessage( ApplID, rmsg, para );
  419.                                 }
  420.                                 break;
  421.  
  422.                             case CAPICMD_INFO:
  423.                                 {
  424.                                     U32 plci;
  425.                                     U16 infonumber;
  426.                                     U8  infosize;
  427.  
  428.                                     GET_PARA( para, U32, plci );
  429.                                     GET_PARA( para, U16, infonumber );
  430.                                     GET_PARA( para, U8, infosize );            /* Grösse der Info-Struct */
  431.                                     if (infonumber & 0x8000) {            /* Bits 7..0 sind Message-Type */
  432.                                         switch (infonumber & 0xFF) {
  433.                                             case D_ALERTING:
  434.                                                 out(debugcapi, "INFO_IND D_Alerting");
  435.                                                 break;
  436.                                             case D_CALL_PROCEEDING:
  437.                                                 out(debugcapi, "INFO_IND D_CallProceeding");
  438.                                                 break;
  439.                                             case D_SETUP_ACKNOWLEDGE:
  440.                                                 out(debugcapi, "INFO_IND D_SetupAcknowledge");
  441.                                                 break;
  442.                                             default:
  443.                                                 out(debugcapi, "INFO_IND UNKNOWN MESSAGE");
  444.                                                 break;
  445.                                         }
  446.                                     } else {                                    /* Bits 7..0 sind Info-Element-Type */
  447.                                         if (infonumber == I_Charging) {
  448.                                             U32 cost;
  449.  
  450.                                             GET_PARA( para, U32, cost);
  451.                                             out(debugcapi, "INFO_IND I_Charging %ld", cost);
  452.                                         } else {
  453.                                             switch (infonumber & 0xFF) {
  454.                                                 case I_ChannelIdentification:
  455.                                                     {
  456.                                                         U8 channelinfo;
  457.  
  458.                                                         GET_PARA( para, U8, channelinfo );
  459.                                                         out(debugcapi, "INFO_IND I_ChannelIdentification 0x%02x", channelinfo);
  460.                                                     }
  461.                                                     break;
  462.  
  463.                                                 case I_Cause:
  464.                                                     {
  465.                                                         U8 cause;
  466.  
  467.                                                         GET_PARA( para, U8, cause );
  468.                                                         out(debugcapi, "INFO_IND I_Cause 0x%02x", cause);
  469.                                                     }
  470.                                                     break;
  471.  
  472.                                                 case I_DateTime:
  473.                                                     {
  474.                                                         U8 year, month, day;
  475.                                                         U8 hour, minute;
  476.  
  477.                                                         GET_PARA( para, U8, year );
  478.                                                         GET_PARA( para, U8, month );
  479.                                                         GET_PARA( para, U8, day );
  480.                                                         GET_PARA( para, U8, hour );
  481.                                                         GET_PARA( para, U8, minute );
  482.                                                         out(debugcapi, "INFO_IND I_DateTime %02d.%02d.%4d %02d:%02d", day, month, year, hour, minute);
  483.                                                     }
  484.                                                     break;
  485.  
  486.                                                 case I_Facility:
  487.                                                     out(debugcapi, "INFO_IND I_Facility");
  488.                                                     break;
  489.  
  490.                                                 default:
  491.                                                     out(debugcapi, "INFO_IND Unknown INFOELEMENT");
  492.                                                     break;
  493.                                             }
  494.                                         }
  495.                                     }
  496.  
  497.                                     /*
  498.                                     ** Antwort-Message zusammenfuegen
  499.                                     */
  500.                                     para = INIT_PARA( rmsg ) + 4;   /* INFO_RESP: Nur PLCI */
  501.                                     rmsg->Subcommand = CAPISUBCMD_RESP;
  502.                                     out(debugcapi, "INFO_RESP : 0x%04lx", error);
  503.                                     error = SendCAPIMessage( ApplID, rmsg, para );
  504.                                 }
  505.                                 break;
  506.  
  507.                             default:
  508.                                 out(debugcapi, "Unknown IND <0x%04x>", rmsg->Command);
  509.                                 break;
  510.                         }
  511.                         break;
  512.  
  513.                     default:
  514.                         out(debugcapi, "Unknown SUBCMD <0x%04x>", rmsg->Subcommand);
  515.                         break;
  516.                 }
  517.             } else {
  518.                 out(debugcapi, "Empty Message !!!");
  519.                 break;
  520.             }
  521.         } else {
  522.             if (error != CAPI_11_MESSAGE_QUEUE_EMPTY)
  523.                 out(debugcapi, "U_CAPI_GET_MESSAGE --> %04lx", error);
  524.             break;
  525.         }
  526.     }
  527. }
  528.  
  529.  
  530. /*****************************************************************************
  531. ** CAPI initialisieren
  532. */
  533. BOOL MYCAPI_Init(U32 ctrlnum)
  534. {
  535.     CAPI_PROFILE    profile;
  536.     U32                error;
  537.     U32                infomask = 0x0000007F;    /* alles was definiert ist */
  538.     U32                cipmask =  0xFFFFFFFF;  /* alle Anruftypen anzeigen
  539.     /*(1L<<CAPI_CIP_SPEECH) | (1L<<CAPI_CIP_AUDIO31);*/
  540.  
  541.     BOOL                ret = FALSE;
  542.     /*U8  number[CAPI_MAX_NUMBER_SIZE];
  543.     U8 name[NAMELEN]; */
  544.  
  545.     /*
  546.     ** Erst mal schauen, ob ctrlnum innerhalb des legalen Bereichs liegt,
  547.     ** und mindestens ein Controller vorhanden ist.
  548.     */
  549.  
  550.     /*number[0]='0';
  551.     number[1]='1';
  552.     number[2]='9';
  553.     number[3]='9';
  554.     number[4]='4';
  555.     number[5]='1';
  556.     number[6]='8';
  557.     number[7]='3';
  558.     number[8]='1';
  559.     number[9]='\0';
  560.     
  561.     GetCallingPartyName(name, number);
  562.     myoutput("%s",name);*/
  563.     error = (U32)U_CAPI_GET_PROFILE( &profile, 0 );
  564.     if (!error) {
  565.         if ((profile.NumControllers != 0) && (ctrlnum > 0) && (ctrlnum <= profile.NumControllers)) {
  566.  
  567.             /*
  568.             ** beim CAPI als Applikation registrieren
  569.             */
  570.             error = (U32)U_CAPI_REGISTER( CAPICONNECTIONS, CAPIBUFFERS, CAPIBLOCKSIZE, &ApplID);
  571.             if (!error) {
  572.                 struct {
  573.                     CAPI_MESSAGE Msg;
  574.                     U8 Para[32];
  575.                 } listen_req;
  576.                 U8 *para = listen_req.Para;
  577.  
  578.                 /*
  579.                 ** CAPI-Signalhandler einbinden
  580.                 */
  581.                 error = (U32)U_CAPI_SET_SIGNAL( ApplID, (U32)SignalHandler, (U32)NULL );
  582.                 if (!error) {
  583.  
  584.                     U_CAPI_GET_MANUFACTURER( manufacturer );
  585.                     U_CAPI_GET_VERSION( version );
  586.                     U_CAPI_GET_SERIAL_NUMBER( serialnumber );
  587.  
  588.                     /* myoutput("Display CallerID  (C) 1996 by ith GmbH");
  589.                     myoutput("%s", manufacturer); */
  590.  
  591.                     if (debugcapi)
  592.                         myoutput("started logging (ApplID:0x%04x)", ApplID);
  593.  
  594.                     /*
  595.                     ** LISTEN_REQ fuer den entsprechenden Controller abschicken.
  596.                     */
  597.                     listen_req.Msg.Command        = CAPICMD_LISTEN;
  598.                     listen_req.Msg.Subcommand    = CAPISUBCMD_REQ;
  599.                     ADD_PARA( para, U32, ctrlnum );        /* Controller */
  600.                     ADD_PARA( para, U32, infomask );        /* Info mask  */
  601.                     ADD_PARA( para, U32, cipmask );        /* CIP mask   */
  602.                     ADD_PARA( para, U32, 0 );                /* CIP mask 2: reserviert        */
  603.                     *para++ = 0;                                /* Calling party number            */
  604.                   *para++ = 0;                                /* Calling party subaddress    */
  605.                   if (debugcapi)
  606.                         myoutput("LISTEN_REQ(0x%08lx, 0x%08lx, 0x%08lx) --> 0x%04lx", ctrlnum, infomask, cipmask, error);
  607.                     error = SendCAPIMessage( ApplID, &listen_req.Msg, para );
  608.                     ret = TRUE;
  609.  
  610.                 } else
  611.                     if (debugcapi)
  612.                         myoutput("U_CAPI_SET_SIGNAL() --> 0x%04lx", error);
  613.             } else
  614.                 if (debugcapi)
  615.                     myoutput("U_CAPI_REGISTER() --> 0x%04lx", error);
  616.         } else
  617.             if (debugcapi)
  618.                 myoutput("Controllernummer nicht im gültigen Bereich.");
  619.     } else
  620.         if (debugcapi)
  621.             myoutput("U_CAPI_GET_PROFILE --> 0x%04lx", error);
  622.  
  623.     return ret;
  624. }
  625.  
  626.  
  627. /*****************************************************************************
  628. ** CAPI-Resourcen freigeben
  629. */
  630. VOID MYCAPI_Exit(VOID)
  631. {
  632.     U32 error;
  633.  
  634.     error = (U32)U_CAPI_RELEASE( ApplID );
  635.     if (debugcapi)
  636.         myoutput("U_CAPI_RELEASE --> 0x%04lx", error);
  637. }
  638.